package com.sixbro.authorization.config.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  定义常用的 Redis操作
 * </p>
 *
 * @author: Mr.Lu
 * @since: 2021/6/15 16:41
 */
@Slf4j
public class RedisService {

    private RedisTemplate redisTemplate;

    public RedisService(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 设置有效时间
     *
     * @param key       Redis键
     * @param timeout   超时时间
     * @param timeUnit  时间单位
     * @return true=设置成功；false=设置失败
     */
    public <T> boolean expire(final String key, final Long timeout, final TimeUnit timeUnit) {
        try {
            if (timeout > 0) {
                redisTemplate.expire(key, timeout, timeUnit);
            }
            return true;
        } catch (Exception e) {
            log.error("Exception: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 设置有效时间
     *
     * @param key       Redis键
     * @param timeout   超时时间
     * @return true=设置成功；false=设置失败
     */
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key       缓存的KEY
     * @param value     缓存的数据
     * @param timeout   过期时间
     * @param timeUnit  过期时间单位
     */
    public <T> void set(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public <T> void set(String key, T value) {
        //key过期时间为120秒
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T get(final String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return key == null ? null : operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean del(final String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */
    public long del(final Collection collection) {
        return redisTemplate.delete(collection);
    }

    /**
     * 缓存List数据
     *
     * @param key 缓存的键值
     * @param data 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> long setList(final String key, final List<T> data) {
        Long count = redisTemplate.opsForList().rightPushAll(key, data);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public <T> List<T> getList(final String key)
    {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 缓存Set
     *
     * @param key 缓存键值
     * @param data 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> long setSet(final String key, final Set<T> data) {
        Long count = redisTemplate.opsForSet().add(key, data);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getSet(final String key)
    {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param data
     */
    public <T> void setMap(final String key, final Map<String, T> data) {
        if (data != null) {
            redisTemplate.opsForHash().putAll(key, data);
        }
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getMap(final String key)
    {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 判断键是否存在
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 删除所有key
     */
    public void flushAll(){
        Set<String> keys = redisTemplate.keys("*");
        redisTemplate.delete(keys);
    }

    /**
     * 建立发布者，通过频道发布消息
     * @param key 发布者
     * @param value 消息
     */
    public void publish(String key, Object value) {
        redisTemplate.convertAndSend(key, value);
    }

}